home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / game / shoot / ADescentSrc.lha / descent / bios / ipx.c next >
C/C++ Source or Header  |  1998-04-13  |  16KB  |  601 lines

  1. // 05/02/1998 trance
  2.  
  3. /*
  4. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  5. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  6. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  7. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  8. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  9. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  10. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  11. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  12. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  13. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  14. */
  15.  
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <assert.h>
  20. #include <sys/types.h>
  21.  
  22. #include "types.h"
  23. #include "ipx.h"
  24.  
  25. #ifdef WANT_IPX
  26.  
  27. #include <proto/exec.h>
  28. #include <inline/amipx.h>
  29.  
  30. struct Library *AMIPX_Library = NULL;
  31.  
  32. #define RETURN_NET_ERRORS { neterrors++; return; }
  33.  
  34. #define FALSE 0
  35. #define TRUE 1
  36.  
  37. #define NO_SOCKET 0
  38.  
  39. #define NO_EVENT 0
  40. #define EVENT_LISTEN 29
  41.  
  42. #define PACKET_FREE -1
  43.  
  44. void got_new_packet( ecb_header * ecb );
  45. void ipx_listen_for_packet( ecb_header * ecb );
  46.  
  47. #define NO_USER 0
  48. #define MAX_USERS 64
  49. int ipx_users = NO_USER;
  50. user_address ipx_user[MAX_USERS];
  51.  
  52. #define NO_NETWORK 0
  53. #define MAX_NETWORKS 64
  54. int ipx_networks = NO_NETWORK;
  55. network_address ipx_network[MAX_NETWORKS];
  56.  
  57. #define NO_PACKET 0
  58. #define MAX_PACKETS 64
  59. int ipx_packets = NO_PACKET;
  60. packet ipx_packet[MAX_PACKETS];
  61.  
  62. static int largest_packet_index = NO_PACKET;
  63. static packet_data packet_buffers[MAX_PACKETS];
  64. static short packet_free_list[MAX_PACKETS];
  65. static short packet_size[MAX_PACKETS];
  66.  
  67. #define NO_ERROR 0
  68. int neterrors = NO_ERROR;
  69.  
  70. ubyte ipx_available = FALSE;
  71. ushort ipx_socket = NO_SOCKET;
  72.  
  73. int ipx_current_packet = NO_PACKET;
  74.  
  75. node_address ipx_node_address;
  76. network_address ipx_network_address;
  77.  
  78.  
  79.  
  80. int ipx_init( word socket_number, bool show_address );
  81. void ipx_close();
  82.  
  83. void free_packet( int packet )
  84.     {
  85.     packet_buffers[ packet ].packet = PACKET_FREE;
  86.     packet_free_list[ --ipx_packets ] = packet;
  87.  
  88.     if ( largest_packet_index == packet )
  89.         {
  90.         while ( ( --largest_packet_index > NO_PACKET ) && ( packet_buffers[ largest_packet_index ].packet == PACKET_FREE ) );
  91.         };
  92.     };
  93.  
  94. int ipx_get_packet_data( byte *data )
  95.     {
  96.     int i, size;
  97.     int n = 0, best = PACKET_FREE, best_id = PACKET_FREE;
  98.  
  99.     for ( i = 1; i < MAX_PACKETS; i++ )
  100.         {
  101.         if ( !ipx_packet[i].ecb.in_use )
  102.             {
  103.             got_new_packet( &ipx_packet[i].ecb );
  104.  
  105.             ipx_packet[i].ecb.in_use = NO_EVENT;
  106.             ipx_listen_for_packet( &ipx_packet[i].ecb );
  107.             };
  108.         };
  109.  
  110.     for (i=0; i<=largest_packet_index; i++ )
  111.         {
  112.         if ( packet_buffers[i].packet > PACKET_FREE )
  113.             {
  114.             n++;
  115.             if ( ( best == PACKET_FREE ) || ( packet_buffers[i].packet < best ) )
  116.                 {
  117.                 best = packet_buffers[i].packet;
  118.                 best_id = i;
  119.                 };
  120.             };
  121.         };
  122.  
  123.     printf( "Best id = %d, pn = %d, ne = %d\n", best_id, best, neterrors );
  124.  
  125.     if ( best_id < NO_PACKET )
  126.         {
  127.         return NO_PACKET;
  128.         };
  129.  
  130.     size = packet_size[best_id];
  131.     memcpy( data, packet_buffers[best_id].data, size );
  132.     free_packet(best_id);
  133.  
  134.     return size;
  135.     };
  136.  
  137. void got_new_packet( ecb_header * ecb )
  138.     {
  139.     packet * p;
  140.     int id;
  141.     unsigned short size=0;
  142.  
  143.     p = (packet *)ecb;
  144.  
  145.     if ( ( p->ecb.in_use ) || ( p->ecb.completion_code ) ) RETURN_NET_ERRORS;
  146.  
  147.     printf( "Receive error %d for completion code", p->ecb.completion_code );
  148.  
  149.     if ( memcmp( &p->ipx.source.node, &ipx_node_address, 6 ) )
  150.         {
  151.         size = p->ipx.length;
  152.         size -= sizeof(ipx_header);
  153.  
  154.         // Find slot to put packet in...
  155.         if ( size > 0 && size <= sizeof(packet_data) )
  156.             {
  157.             if ( ipx_packets >= MAX_PACKETS )
  158.                 {
  159.                 printf( "IPX: Packet buffer overrun!!!\n" );
  160.                 RETURN_NET_ERRORS;
  161.                 };
  162.  
  163.             id = packet_free_list[ ipx_packets++ ];
  164.             if (id > largest_packet_index ) largest_packet_index = id;
  165.             packet_size[id] = size - sizeof( int );
  166.             packet_buffers[id].packet =  p->pd.packet;
  167.             if ( packet_buffers[id].packet < NO_PACKET ) RETURN_NET_ERRORS;
  168.             memcpy( packet_buffers[id].data, p->pd.data, packet_size[id] );
  169.             }
  170.         else RETURN_NET_ERRORS;
  171.         };
  172.  
  173.     // Repost the ecb
  174.     p->ecb.in_use = NO_EVENT;
  175.     //ipx_listen_for_packet(&p->ecb);
  176.     };
  177.  
  178. node_address *ipx_get_my_local_address()
  179.     {
  180.     return &ipx_node_address;
  181.     };
  182.  
  183. network_address *ipx_get_my_server_address()
  184.     {
  185.     return &ipx_network_address;
  186.     };
  187.  
  188. void ipx_listen_for_packet( ecb_header * ecb )
  189.     {
  190.     word error;
  191.  
  192.     ecb->in_use = EVENT_LISTEN;
  193.  
  194.     if ( ( error = AMIPX_ListenForPacket( ecb ) ) )
  195.         {
  196.         printf("IPX: ListenForPacket failed return code %d.\n", error);
  197.         };
  198.     };
  199.  
  200. void ipx_cancel_listen_for_packet(ecb_header * ecb )
  201.     {
  202.     AMIPX_RelinquishControl();
  203.     };
  204.  
  205. void ipx_send_packet(ecb_header * ecb )
  206.     {
  207.     word error;
  208.  
  209.     if ( ( error = AMIPX_SendPacket( ecb ) ) )
  210.         {
  211.         printf("IPX: SendPacket failed return code %d.\n", error);
  212.         };
  213.     };
  214.  
  215. void ipx_get_local_target( network_address *network, node_address *node, node_address *address )
  216.     {
  217.     net_address ipx_net_address;
  218.     node_address ipx_node_address;
  219.  
  220.     memcpy( &ipx_net_address.network, &network, NETWORK_SPACE );
  221.     memcpy( &ipx_net_address.node, &node, ADDRESS_SPACE );
  222.     ipx_net_address.socket = NO_SOCKET;
  223.  
  224.     if ( ( AMIPX_GetLocalTarget( &ipx_net_address, &ipx_node_address ) ) )
  225.         {
  226.         printf("IPX: unable to get local target!\n");
  227.         }
  228.     else
  229.         {
  230.         // Save the local target...
  231.         memcpy( &address, &ipx_node_address, ADDRESS_SPACE );
  232.         };
  233.     };
  234.  
  235. void ipx_close()
  236.     {
  237.     if ( ipx_available )
  238.         {
  239.         AMIPX_CloseSocket( ipx_socket );
  240.         ipx_available = FALSE;
  241.         };
  242.  
  243.     if ( AMIPX_Library )
  244.         {
  245.         CloseLibrary( AMIPX_Library );
  246.         AMIPX_Library = NULL;
  247.         };
  248.     };
  249.  
  250. //---------------------------------------------------------------
  251. // Initializes all IPX internals.
  252. // If socket_number==0, then opens next available socket.
  253. // Returns: 0  if successful.
  254. //              -1 if socket already open.
  255. //              -2 if socket table full.
  256. //              -3 if IPX not installed.
  257. //              -4 if couldn't allocate low dos memory
  258. //              -5 if error with getting internetwork address
  259.  
  260. int ipx_init( word socket_number, bool show_address )
  261.     {
  262.     net_address ipx_net_address;
  263.     int i;
  264.  
  265.     ipx_current_packet = NO_PACKET;
  266.  
  267.     // init packet buffers.
  268.     for ( i = 0; i < MAX_PACKETS; i++ )
  269.         {
  270.         packet_buffers[i].packet = PACKET_FREE;
  271.         packet_free_list[i] = i;
  272.         };
  273.  
  274.     ipx_packets = largest_packet_index = NO_PACKET;
  275.  
  276.     if ( ( AMIPX_Library = (void *)OpenLibrary( AMIPXNAME, AMIPXVERSION ) ) )
  277.         {
  278.         atexit(ipx_close);
  279.  
  280.         // Open a socket for IPX
  281.         ipx_socket = AMIPX_OpenSocket( socket_number );
  282.  
  283.         if ( ipx_socket == NO_SOCKET )
  284.             {
  285.             printf( "IPX error opening channel %d\n", socket_number - IPX_DEFAULT_SOCKET );
  286.             return -2;
  287.             };
  288.  
  289.         ipx_available = TRUE;
  290.  
  291.         // Find our internetwork address
  292.         AMIPX_GetLocalAddress( &ipx_net_address );
  293.  
  294.         memcpy( &ipx_network_address, &ipx_net_address.network, NETWORK_SPACE );
  295.         memcpy( &ipx_node_address, &ipx_net_address.node, ADDRESS_SPACE );
  296.  
  297.         ipx_networks = NO_NETWORK;
  298.         memcpy( &ipx_network[ ipx_networks++ ], &ipx_network_address, NETWORK_SPACE );
  299.  
  300.         if ( show_address )
  301.             {
  302.             printf( "My IPX addresss is " );
  303.             printf( "%02X%02X%02X%02X/", ipx_net_address.network.address[0],ipx_net_address.network.address[1],ipx_net_address.network.address[2],ipx_net_address.network.address[3] );
  304.             printf( "%02X%02X%02X%02X%02X%02X\n", ipx_net_address.node.address[0],ipx_net_address.node.address[1],ipx_net_address.node.address[2],ipx_net_address.node.address[3],ipx_net_address.node.address[4],ipx_net_address.node.address[5] );
  305.             printf( "\n" );
  306.             };
  307.  
  308.         memset( ipx_packet, 0, sizeof( packet ) * MAX_PACKETS );
  309.  
  310.         for ( i = 1; i < MAX_PACKETS; i++ )
  311.             {
  312.             ipx_packet[i].ecb.in_use = EVENT_LISTEN;
  313.             ipx_packet[i].ecb.socket = ipx_socket;
  314.             ipx_packet[i].ecb.fragment_count = 1;
  315.             ipx_packet[i].ecb.fragment_pointer = (byte *)&ipx_packet[i].ipx;
  316.             ipx_packet[i].ecb.fragment_size = sizeof( packet ) - sizeof( ecb_header );
  317.  
  318.             ipx_listen_for_packet( &ipx_packet[i].ecb );
  319.             };
  320.  
  321.         ipx_packet[0].ecb.socket = ipx_socket;
  322.         ipx_packet[0].ecb.fragment_count = 1;
  323.         ipx_packet[0].ecb.fragment_pointer = (byte *)&ipx_packet[0].ipx;
  324.         ipx_packet[0].ipx.packet_type = PACKET_IPX;
  325.         ipx_packet[0].ipx.destination.socket = ipx_socket;
  326.         }
  327.     else
  328.         {
  329.         printf("IPX: unable to open network library.\n");
  330.         };
  331.  
  332.     return 0;
  333.     };
  334.  
  335. void ipx_send_packet_data( byte *data, int size, network_address *network, node_address *node, node_address *address )
  336.     {
  337.     assert( ipx_available );
  338.  
  339.     if ( size >= IPX_MAX_DATA_SIZE )
  340.         {
  341.         printf( "Data too big\n" );
  342.  
  343.         exit(1);
  344.         };
  345.  
  346.     // Make sure no one is already sending something
  347.     while( ipx_packet[0].ecb.in_use );
  348.  
  349.     if ( ipx_packet[0].ecb.completion_code )
  350.         {
  351.         printf( "Send error %d for completion code\n", ipx_packet[0].ecb.completion_code );
  352.  
  353.         exit(1);
  354.         };
  355.  
  356.     // Fill in destination address
  357.     if ( memcmp( network->address, ipx_network_address.address, NETWORK_SPACE ) )
  358.         {
  359.         memcpy( ipx_packet[0].ipx.destination.network.address, network, NETWORK_SPACE );
  360.         }
  361.     else
  362.         {
  363.         memset( ipx_packet[0].ipx.destination.network.address, 0, NETWORK_SPACE );
  364.         };
  365.  
  366.     memcpy( ipx_packet[0].ipx.destination.node.address, node, ADDRESS_SPACE );
  367.     memcpy( ipx_packet[0].ecb.immediate_address.address, address, ADDRESS_SPACE );
  368.     ipx_packet[0].pd.packet = ipx_current_packet++;
  369.  
  370.     // Fill in data to send
  371.     ipx_packet[0].ecb.fragment_size = sizeof( ipx_header ) + sizeof( int ) + size;
  372.  
  373.     assert( size > 1 );
  374.     assert( ipx_packet[0].ecb.fragment_size <= MAX_DATAGRAM_SIZE );
  375.  
  376.     memcpy( ipx_packet[0].pd.data, data, size );
  377.  
  378.     // Send it
  379.     ipx_send_packet( &ipx_packet[0].ecb );
  380.     };
  381.  
  382. void ipx_send_broadcast_packet_data( byte *data, int size )
  383.     {
  384.     int i, j;
  385.     node_address broadcast = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
  386.     node_address node;
  387.  
  388.     // Set to all networks besides mine
  389.     for ( i = 0; i < ipx_networks; i++ )
  390.         {
  391.         if ( memcmp( &ipx_network[i], &ipx_network_address, 4 ) )
  392.             {
  393.             ipx_get_local_target( &ipx_network[i], &broadcast, &node );
  394.             ipx_send_packet_data( data, size, &ipx_network[i], &broadcast, &node );
  395.             }
  396.         else
  397.             {
  398.             ipx_send_packet_data( data, size, &ipx_network[i], &broadcast, &broadcast );
  399.             };
  400.         };
  401.  
  402.     // Send directly to all users not on my network or in the network list.
  403.     for ( i = 0; i < ipx_users; i++ )
  404.         {
  405.         if ( memcmp( &ipx_user[i].network, &ipx_network_address, NETWORK_SPACE ) )
  406.             {
  407.             for ( j = 0; j < ipx_networks; j++ )
  408.                 {
  409.                 if ( !memcmp( &ipx_user[i].network, &ipx_network[j], NETWORK_SPACE ) )
  410.                     goto SkipUser;
  411.                 };
  412.  
  413.             ipx_send_packet_data( data, size, &ipx_user[i].network, &ipx_user[i].node, &ipx_user[i].user );
  414. SkipUser:
  415.             j = 0;
  416.             };
  417.         };
  418.     };
  419.  
  420. // Sends a non-localized packet... needs 4 byte server, 6 byte address
  421. void ipx_send_internetwork_packet_data( byte *data, int size, network_address *network, node_address *node )
  422.     {
  423.     node_address address;
  424.  
  425.     if ( (*(long *)network) != NULL )
  426.         {
  427.         ipx_get_local_target( network, node, &address );
  428.         ipx_send_packet_data( data, size, network, node, &address );
  429.         }
  430.     else
  431.         {
  432.         // Old method, no server info.
  433.         ipx_send_packet_data( data, size, network, node, node );
  434.         };
  435.     };
  436.  
  437. int ipx_change_default_socket( word socket_number )
  438.     {
  439.     int i;
  440.     word new_ipx_socket;
  441.  
  442.     if ( !ipx_available ) return -3;
  443.  
  444.     // Open a new socket
  445.     new_ipx_socket = AMIPX_OpenSocket( socket_number );
  446.  
  447.     if ( ipx_socket == NO_SOCKET )
  448.         {
  449.         printf( "IPX error opening channel %d\n", socket_number - IPX_DEFAULT_SOCKET );
  450.  
  451.         return -2;
  452.         };
  453.  
  454.     for ( i = 1; i < MAX_PACKETS; i++ )
  455.         {
  456.         ipx_cancel_listen_for_packet( &ipx_packet[i].ecb );
  457.         };
  458.  
  459.     // Close existing socket...
  460.     AMIPX_CloseSocket( ipx_socket );
  461.  
  462.     ipx_socket = new_ipx_socket;
  463.  
  464.     // Repost all listen requests on the new socket...
  465.     for ( i = 1; i < MAX_PACKETS; i++ )
  466.         {
  467.         ipx_packet[i].ecb.in_use = NO_EVENT;
  468.         ipx_packet[i].ecb.socket = ipx_socket;
  469.  
  470.         ipx_listen_for_packet( &ipx_packet[i].ecb );
  471.         };
  472.  
  473.     ipx_packet[0].ecb.socket = ipx_socket;
  474.     ipx_packet[0].ipx.destination.socket = ipx_socket;
  475.  
  476.     ipx_current_packet = NO_PACKET;
  477.  
  478.     // init packet buffers.
  479.     for ( i = 0; i < MAX_PACKETS; i++ )
  480.         {
  481.         packet_buffers[i].packet = PACKET_FREE;
  482.         packet_free_list[i] = i;
  483.         };
  484.  
  485.     ipx_packets = largest_packet_index = NO_PACKET;
  486.  
  487.     return 0;
  488.     };
  489.  
  490. void ipx_read_user_file(char * filename)
  491.     {
  492.     FILE * fp;
  493.     user_address tmp;
  494.     char temp_line[132], *p1;
  495.     int n, ln=0;
  496.  
  497.     if ( !filename ) return;
  498.  
  499.     ipx_users = NO_USER;
  500.  
  501.     fp = fopen( filename, "rt" );
  502.     if ( !fp ) return;
  503.  
  504.     printf( "Broadcast Users:\n" );
  505.  
  506.     while ( fgets( temp_line, 132, fp ) )
  507.         {
  508.         ln++;
  509.         p1 = strchr(temp_line,'\n'); if (p1) *p1 = '\0';
  510.         p1 = strchr(temp_line,';'); if (p1) *p1 = '\0';
  511.         n = sscanf( temp_line, "%2x%2x%2x%2x/%2x%2x%2x%2x%2x%2x", (int *)&tmp.network.address[0], (int *)&tmp.network.address[1], (int *)&tmp.network.address[2], (int *)&tmp.network.address[3], (int *)&tmp.node.address[0], (int *)&tmp.node.address[1], (int *)&tmp.node.address[2], (int *)&tmp.node.address[3], (int *)&tmp.node.address[4], (int *)&tmp.node.address[5] );
  512.         if ( n != 10 ) continue;
  513.         if ( ipx_users < MAX_USERS )
  514.             {
  515.             ipx_get_local_target( &tmp.network, &tmp.node, &tmp.user );
  516.             ipx_user[ipx_users++] = tmp;
  517.             printf( "%02X%02X%02X%02X/", tmp.network.address[0],tmp.network.address[1],tmp.network.address[2],tmp.network.address[3] );
  518.             printf( "%02X%02X%02X%02X%02X%02X\n", tmp.node.address[0],tmp.node.address[1],tmp.node.address[2],tmp.node.address[3],tmp.node.address[4],tmp.node.address[5] );
  519.             }
  520.         else
  521.             {
  522.             printf( "Too many addresses in %s! (Limit of %d)\n", filename, MAX_USERS );
  523.             fclose(fp);
  524.             return;
  525.             };
  526.         };
  527.  
  528.     fclose(fp);
  529.     };
  530.  
  531. void ipx_read_network_file(char * filename)
  532.     {
  533.     FILE * fp;
  534.     user_address tmp;
  535.     char temp_line[132], *p1;
  536.     int i, n, ln=0;
  537.  
  538.     if ( !filename ) return;
  539.  
  540.     fp = fopen( filename, "rt" );
  541.     if ( !fp ) return;
  542.  
  543.     printf( "Using Networks:\n" );
  544.  
  545.     for ( i = 0; i < ipx_networks; i++ )
  546.         {
  547.         printf("* %02x%02x%02x%02x\n", ipx_network[i].address[0], ipx_network[i].address[1], ipx_network[i].address[2], ipx_network[i].address[3] );
  548.         };
  549.  
  550.     while (fgets(temp_line, 132, fp))
  551.         {
  552.         ln++;
  553.         p1 = strchr(temp_line,'\n'); if (p1) *p1 = '\0';
  554.         p1 = strchr(temp_line,';'); if (p1) *p1 = '\0';
  555.         n = sscanf( temp_line, "%2x%2x%2x%2x", (int *)&tmp.network.address[0], (int *)&tmp.network.address[1], (int *)&tmp.network.address[2], (int *)&tmp.network.address[3] );
  556.         if ( n != 4 ) continue;
  557.         if ( ipx_networks < MAX_NETWORKS  )
  558.             {
  559.             int j;
  560.  
  561.             for (j=0; j<ipx_networks; j++ )
  562.                 if ( !memcmp( &ipx_network[j], &tmp.network, NETWORK_SPACE ) )
  563.                     break;
  564.  
  565.             if ( j >= ipx_networks )
  566.                 {
  567.                 memcpy( &ipx_network[ipx_networks++], &tmp.network, NETWORK_SPACE );
  568.                 printf("  %02x%02x%02x%02x\n", tmp.network.address[0], tmp.network.address[1], tmp.network.address[2], tmp.network.address[3] );
  569.                 };
  570.             }
  571.         else
  572.             {
  573.             printf( "Too many networks in %s! (Limit of %d)\n", filename, MAX_NETWORKS );
  574.             fclose(fp);
  575.             return;
  576.             };
  577.         };
  578.  
  579.     fclose(fp);
  580.     };
  581.  
  582. #else
  583. void free_packet( int packet ) { };
  584. int ipx_get_packet_data( byte *data ) { return 0; };
  585. void got_new_packet( ecb_header * ecb ) { };
  586. node_address *ipx_get_my_local_address() { return 0; };
  587. network_address *ipx_get_my_server_address() { return 0; };
  588. void ipx_listen_for_packet( ecb_header * ecb ) { };
  589. void ipx_cancel_listen_for_packet(ecb_header * ecb ) { };
  590. void ipx_send_packet(ecb_header * ecb ) { };
  591. void ipx_get_local_target( network_address *network, node_address *node, node_address *address ) { };
  592. void ipx_close() { };
  593. int ipx_init( word socket_number, bool show_address ) { return -3; };
  594. void ipx_send_packet_data( byte *data, int size, network_address *network, node_address *node, node_address *address ) { };
  595. void ipx_send_broadcast_packet_data( byte *data, int size ) { };
  596. void ipx_send_internetwork_packet_data( byte *data, int size, network_address *network, node_address *node ) { };
  597. int ipx_change_default_socket( word socket_number ) { return 0; };
  598. void ipx_read_user_file(char * filename) { };
  599. void ipx_read_network_file(char * filename) { };
  600. #endif
  601.